package com.lumlord.common.spring;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import com.lumlord.common.database.DynamicDataSource;

@Aspect
@Configuration
public class TransactionAdviceConfig {
	//@Autowired
	//private DataSource dataSource;
	@Autowired
	private DynamicDataSource dynamicDataSource;
	
	@Bean("transactionManager")
	public PlatformTransactionManager annotationDrivenTransactionManager() {
	    return new DataSourceTransactionManager(dynamicDataSource);
	}
	 
	 
	private static final int TX_METHOD_TIMEOUT = 50000;
 
	 
	// 事务的实现Advice
	@Bean
	public TransactionInterceptor txAdvice(@Qualifier("transactionManager")PlatformTransactionManager m) {
	    NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
	    RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
	    readOnlyTx.setReadOnly(true);
	    readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
	    RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
	    requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
	  requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
	    requiredTx.setTimeout(TX_METHOD_TIMEOUT);
	    Map<String, TransactionAttribute> txMap = new HashMap<>();
	    txMap.put("add*", requiredTx);
	    txMap.put("save*", requiredTx);
	    txMap.put("insert*", requiredTx);
	    txMap.put("update*", requiredTx);
	    txMap.put("delete*", requiredTx);
	    txMap.put("create*", requiredTx);

	    txMap.put("get*", readOnlyTx);
	    txMap.put("query*", readOnlyTx);
	    source.setNameMap(txMap);
	    
	    TransactionInterceptor txAdvice = new TransactionInterceptor(m, source);
	    return txAdvice;
	}
	 
	// 切面的定义,pointcut及advice
	@Bean
	public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor txAdvice) {
	    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
	    pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
	    return new DefaultPointcutAdvisor(pointcut, txAdvice);
	}
     private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.lumlord.service.*.*(..))";
 
      
}
